package com.mike.bdb.ui;

import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TextCellEditor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Spinner;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.mike.bdb.manager.DBManager;
import com.mike.bdb.ui.provider.table.MikeQueryTableContentProvider;
import com.mike.bdb.ui.provider.table.MikeSecondaryTableContentProvider;
import com.mike.bdb.ui.provider.table.MikeSecondaryTableLabelProvider;
import com.mike.bdb.ui.provider.table.MikeTableCellModifier;
import com.mike.bdb.ui.provider.table.MikeTableContentProvider;
import com.mike.bdb.ui.provider.table.MikeTableLabelProvider;
import com.mike.bdb.ui.provider.table.MikeTableViewerSorter;
import com.mike.bdb.util.ClassNameUtil;
import com.mike.bdb.util.DataCurrent;
import com.mike.bdb.util.ImageManager;
import com.mike.bdb.util.ReflectUtil;
import com.mike.swt.util.ShellUtil;
import com.sleepycat.persist.EntityCursor;
import com.sleepycat.persist.EntityStore;
import com.sleepycat.persist.ForwardCursor;
import com.sleepycat.persist.SecondaryIndex;

public class QueryConditionEntityTable {

	private static final Logger LOG = LoggerFactory.getLogger(QueryConditionEntityTable.class);
	
	private static final int PAGE_BUTTON_WIDTH = 50;
	
	private Shell motherland;
	protected Shell shell;
	private volatile boolean open = false;
	private Table table;
	private TableViewer tableViewer;
	private Spinner pageSpinner;
	private Label pageLabel;
	private MikeQueryTableContentProvider queryProvider = new MikeQueryTableContentProvider();
	
	public QueryConditionEntityTable(Shell motherland) {
		this.motherland = motherland;
	}
	
	public boolean isOpen() {
		return open;
	}

	/**
	 * Launch the application.
	 * @param args
	 */
	public static void main(String[] args) {
		try {
			QueryConditionEntityTable window = new QueryConditionEntityTable(null);
			window.open(null, null);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * Open the window.
	 */
	public void open(Map<Method, Text> methodMap,
			HashMap<String, Type> methodReturnMap) {
		Display display = Display.getDefault();
		updataDataCurrent(methodMap, methodReturnMap);
		createContents(methodMap, methodReturnMap);
		resetPageIndex();
		shell.open();
		open = true;
		shell.layout();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch()) {
				display.sleep();
			}
		}
		open = false;
	}

	/**
	 * Create contents of the window.
	 */
	protected void createContents(Map<Method, Text> methodMap,
			HashMap<String, Type> methodReturnMap) {
		shell = new Shell(SWT.MAX | SWT.RESIZE | SWT.CLOSE | SWT.BORDER | SWT.APPLICATION_MODAL);
		shell.setImage(ImageManager.getImage(ImageManager.ICON_TABLE_EDIT));
		
		//TODO 二级界面 动态大小
		//shell.setSize(motherland.getClientArea().width * 3 / 4, motherland.getClientArea().height * 3 / 4);
		shell.setSize(600, 400);
		
		
		shell.setText(DataCurrent.getInstance().curDataBasePath 
				+ MainWindow.SPLIT_PATH_CLASS 
				+ ClassNameUtil.getSimpleName(DataCurrent.getInstance().curStoreClazz));
		
		shell.setLayout(new FillLayout(SWT.HORIZONTAL));
		{
			{
				{
					Composite composite = new Composite(shell, SWT.NONE);
					composite.setLayout(new GridLayout(13, false));
					new Label(composite, SWT.NONE);
					new Label(composite, SWT.NONE);
					new Label(composite, SWT.NONE);
					new Label(composite, SWT.NONE);
					new Label(composite, SWT.NONE);
					new Label(composite, SWT.NONE);
					new Label(composite, SWT.NONE);
					new Label(composite, SWT.NONE);
					new Label(composite, SWT.NONE);
					new Label(composite, SWT.NONE);
					new Label(composite, SWT.NONE);
					new Label(composite, SWT.NONE);
					new Label(composite, SWT.NONE);
					new Label(composite, SWT.NONE);
					{
						tableViewer = new TableViewer(composite, SWT.BORDER | SWT.FULL_SELECTION | SWT.MULTI);
						table = tableViewer.getTable();
						table.setHeaderVisible(true);
						table.setLinesVisible(true);
						
						initTable(methodMap, methodReturnMap);
						
						table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 10, 1));
						
						initTableHeader();
						
					}
					new Label(composite, SWT.NONE);
					{
						Label label = new Label(composite, SWT.NONE);
					}
					{
						Label label = new Label(composite, SWT.NONE);
					}
					new Label(composite, SWT.NONE);
					new Label(composite, SWT.NONE);
					new Label(composite, SWT.NONE);
					new Label(composite, SWT.NONE);
					new Label(composite, SWT.NONE);
					new Label(composite, SWT.NONE);
					new Label(composite, SWT.NONE);
					new Label(composite, SWT.NONE);
					new Label(composite, SWT.NONE);
					new Label(composite, SWT.NONE);
					new Label(composite, SWT.NONE);
					new Label(composite, SWT.NONE);
					new Label(composite, SWT.NONE);
					{
						Button button = new Button(composite, SWT.NONE);
						button.addSelectionListener(new SelectionAdapter() {
							@Override
							public void widgetSelected(SelectionEvent arg0) {
								apexLeft();
							}

						});
						{
							GridData gridData = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1);
							gridData.widthHint = PAGE_BUTTON_WIDTH;
							button.setLayoutData(gridData);
						}
						button.setText(Messages.getString("MainWindow.button_1.text")); //$NON-NLS-1$
					}
					{
						Button button = new Button(composite, SWT.NONE);
						button.addSelectionListener(new SelectionAdapter() {
							@Override
							public void widgetSelected(SelectionEvent arg0) {
								leftPage();
							}
						});
						{
							GridData gridData = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1);
							gridData.widthHint = PAGE_BUTTON_WIDTH;
							button.setLayoutData(gridData);
						}
						button.setText(Messages.getString("MainWindow.button_left.text")); //$NON-NLS-1$
					}
					{
						Label label = new Label(composite, SWT.NONE);
						label.setAlignment(SWT.RIGHT);
						{
							GridData gridData = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1);
							gridData.widthHint = 18;
							label.setLayoutData(gridData);
						}
						label.setText(Messages.getString("SecondaryEntityTable.label.text_1")); //$NON-NLS-1$
					}
					{
						pageSpinner = new Spinner(composite, SWT.BORDER);
						pageSpinner.addSelectionListener(new SelectionAdapter() {
							@Override
							public void widgetSelected(SelectionEvent arg0) {
								changePageCount(pageSpinner.getText());
							}
						});
						{
							GridData gridData = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1);
							gridData.widthHint = 30;
							pageSpinner.setLayoutData(gridData);
						}
						pageSpinner.setMinimum(1);
						pageSpinner.setMaximum(Integer.MAX_VALUE);
						pageSpinner.setTextLimit(Integer.MAX_VALUE);
					}
					{
						Label label = new Label(composite, SWT.NONE);
						{
							GridData gridData = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1);
							gridData.widthHint = 28;
							label.setLayoutData(gridData);
						}
						label.setText(Messages.getString("SecondaryEntityTable.label.text")); //$NON-NLS-1$
					}
					{
						Button button = new Button(composite, SWT.NONE);
						button.addSelectionListener(new SelectionAdapter() {
							@Override
							public void widgetSelected(SelectionEvent arg0) {
								rightPage();
							}
						});
						{
							GridData gridData = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1);
							gridData.widthHint = PAGE_BUTTON_WIDTH;
							button.setLayoutData(gridData);
						}
						button.setText(Messages.getString("MainWindow.button_rigth.text")); //$NON-NLS-1$
					}
					{
						Button button = new Button(composite, SWT.NONE);
						button.addSelectionListener(new SelectionAdapter() {
							@Override
							public void widgetSelected(SelectionEvent arg0) {
								apexRight();
							}
						});
						{
							GridData gridData = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1);
							gridData.widthHint = PAGE_BUTTON_WIDTH;
							button.setLayoutData(gridData);
						}
						button.setText(Messages.getString("MainWindow.button_1.text_1")); //$NON-NLS-1$
					}
					{
						pageLabel = new Label(composite, SWT.NONE);
						pageLabel.setAlignment(SWT.CENTER);
						{
							GridData gridData = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1);
							gridData.widthHint = 123;
							pageLabel.setLayoutData(gridData);
						}
						pageLabel.setText("共 1 页");
					}
					new Label(composite, SWT.NONE);
					new Label(composite, SWT.NONE);
					new Label(composite, SWT.NONE);
					new Label(composite, SWT.NONE);
					{
						Label label = new Label(composite, SWT.NONE);
					}
					new Label(composite, SWT.NONE);
					new Label(composite, SWT.NONE);
					new Label(composite, SWT.NONE);
					new Label(composite, SWT.NONE);
					new Label(composite, SWT.NONE);
					new Label(composite, SWT.NONE);
					new Label(composite, SWT.NONE);
					new Label(composite, SWT.NONE);
					new Label(composite, SWT.NONE);
					new Label(composite, SWT.NONE);
					new Label(composite, SWT.NONE);
					new Label(composite, SWT.NONE);
				}
			}
		}
		if (null != motherland) {
			ShellUtil.setCenter(shell, motherland);
		}
	}

	private void initTableHeader() {
		
		if(null == tableViewer) return;
		
		String curStoreClazz = DataCurrent.getInstance().curStoreClazz;
		if(null == curStoreClazz) return;
		
		Class<Object> classBy = ReflectUtil.getClassBy(curStoreClazz);
		if(null == classBy) return;
		
		List<Method> berkeleyAttribute = ReflectUtil.getBerkeleyAttribute(classBy);
		
		int colnumCount = 0;
		
		TableColumn tableColumn = null;
		
		List<String> colnumName = new ArrayList<String>();
		
		HashMap<String, Type> methodReturnMap = new HashMap<String, Type>();
		
		for (Method m : berkeleyAttribute) {
			tableColumn = new TableColumn(table, SWT.NONE);
			colnumName.add(m.getName());
			methodReturnMap.put(m.getName(), m.getGenericReturnType());
			tableColumn.setText(m.getName().replace("get", ""));
			tableColumn.setWidth(16 * m.getName().length());
			tableColumn.setMoveable(true);
			addSortListener(tableColumn, tableViewer, m);
			colnumCount ++;
		}
		
		table.setHeaderVisible(true);
		table.setLinesVisible(true);

		// Create the cell editors
	    CellEditor[] editors = new CellEditor[colnumCount + 1];
	    for (int i = 0; i < editors.length; i++) {
	    	editors[i] = new TextCellEditor(table);
		}
	    // Set the editors, cell modifier, and column properties
	    tableViewer.setColumnProperties(colnumName.toArray(new String[0]));
	    tableViewer.setCellModifier(new MikeTableCellModifier(tableViewer, methodReturnMap));
	    tableViewer.setCellEditors(editors);
	    tableViewer.setInput("not null");
		tableViewer.refresh();
		initColor();
		
	}

	private void initTable(Map<Method, Text> methodMap,
			HashMap<String, Type> methodReturnMap) {
		if(null != tableViewer) {
			queryProvider.setSee(methodMap, methodReturnMap);
			tableViewer.setContentProvider(queryProvider);
			tableViewer.setLabelProvider(new MikeSecondaryTableLabelProvider());
			tableViewer.setSorter(new MikeTableViewerSorter());
		}
	}
	
	/***
	 * 设置字段的排序监听适配器
	 * @param tableColumn
	 * @param tableViewer
	 * @param m
	 */
	private void addSortListener(TableColumn tableColumn, final TableViewer tableViewer, final Method m) {
		tableColumn.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent event) {
				((MikeTableViewerSorter) tableViewer.getSorter()).doSort(m.getName());
				tableViewer.refresh();
			}
		});
	}
	
	private void initColor() {
		if(null == tableViewer) return;
		Table table = tableViewer.getTable();
		TableItem[] items = table.getItems();
		int index = 0;
		for (TableItem item: items) {
			if (index % 2 != 0) {
				if(null != MainWindow.getCurrentColorEven()) item.setBackground(MainWindow.getCurrentColorEven());
			} else {
				if(null != MainWindow.getCurrentColorOdd()) item.setBackground(MainWindow.getCurrentColorOdd());
			}
			index++;
		}
	}

	/** 第一页 */
	private void apexLeft() {
		DataCurrent.getInstance().getQueryPageInfo().setIndex(0);
		resetPageIndex();
		refreshActiveViewer();
	}
	
	/** 上一页 */
	private void leftPage() {
		//TODO <!分页2> 上一页
		int currentPage = DataCurrent.getInstance().getQueryPageInfo().getIndex();
		if(currentPage > 0) {
			DataCurrent.getInstance().getQueryPageInfo().setIndex(currentPage - 1);
		}
		resetPageIndex();
		refreshActiveViewer();
	}
	
	/** 下一页 */
	private void rightPage() {
		//TODO <!分页2> 下一页
		int currentPage = DataCurrent.getInstance().getQueryPageInfo().getIndex();
		int maxPage = DataCurrent.getInstance().getQueryPageInfo().getMaxPage();
		if(++currentPage < maxPage) {
			DataCurrent.getInstance().getQueryPageInfo().setIndex(currentPage);
		}
		resetPageIndex();
		refreshActiveViewer();
		
	}
	
	/** 最后一页 */
	private void apexRight() {
		//TODO <!分页2> 最后一页
		DataCurrent.getInstance().getQueryPageInfo().setIndex(
				DataCurrent.getInstance().getQueryPageInfo().getMaxPage() - 1);
		resetPageIndex();
		refreshActiveViewer();
	}

	/** 刷新活动表格 */
	public void refreshActiveViewer() {
		if(null != tableViewer) {
			tableViewer.refresh();
		}
	}
	
	public void resetPageIndex() {
		//TODO <!分页2> 设置当前页标签
		int index = DataCurrent.getInstance().getQueryPageInfo().getIndex() + 1;
		
		if(null != pageSpinner) {
			if(!pageSpinner.isFocusControl()) {
				pageSpinner.setSelection(index);
			}
		}
		
		if(null != pageLabel) {
			pageLabel.setText( " 共 " +
					DataCurrent.getInstance().getQueryPageInfo().getMaxPage()
					+ " 页");
		}
	}

	/**
	 * 计算分页数据
	 * @param keyName
	 */
	private void updataDataCurrent(Map<Method, Text> methodMap,
			HashMap<String, Type> methodReturnMap) {
		
		if(methodMap.size() <= 0
				|| methodReturnMap.size() <= 0) return;
		
		String curStoreClazz = DataCurrent.getInstance().curStoreClazz;
		if(null == curStoreClazz) return;
		
		Class<Object> classBy = ReflectUtil.getClassBy(curStoreClazz);
		if(null == classBy) return;
		
		Class pkClass = ReflectUtil.getPKClass(classBy);

		//TODO 计算分页数
		/*skName = skName.substring(0, 1).toLowerCase() + skName.substring(1, skName.length());
		
		Class skClass = ReflectUtil.getSKClass(classBy, skName);

		SecondaryIndex store = DBManager.getInstance().getSKStore(pkClass, classBy, skClass, skName);

		long count = store.subIndex(ReflectUtil.getRealType(skClass, keyContext)).count();*/
		
		ForwardCursor allFieldSKStore = DBManager.getInstance().getAllFieldSKStore(methodMap, methodReturnMap);
		
		int count = 0;
		
		if(null != allFieldSKStore) {
			for (Object object : allFieldSKStore) {
				count++;
			}
		}
		
		if(null != allFieldSKStore) {
			allFieldSKStore.close();
		}
		
		DataCurrent.getInstance().getQueryPageInfo().setCount((int) count);
		
		if (LOG.isDebugEnabled()) {
			LOG.debug(" 按条件查询 >> " + count);
		}
		
	}
	
	/**
	 * 改变当前页数
	 * @param text
	 */
	private void changePageCount(String text) {
		//TODO <!分页> 改变当前页数 
		if(null == text) return;
		
		int maxPage = DataCurrent.getInstance().getQueryPageInfo().getMaxPage();
		
		int parseInt = 0;
		
		try {
			parseInt = Integer.parseInt(text);
		} catch (Exception e) {
			//eat it.
		}
		
		if(parseInt > maxPage) {
			parseInt = maxPage;
		}
		
		if(parseInt <= 0) {
			parseInt = 1;
		}
		
		parseInt = parseInt > 0 ? parseInt - 1 : parseInt;
		
		DataCurrent.getInstance().getQueryPageInfo().setIndex(parseInt);
		resetPageIndex();
		refreshActiveViewer();
	}
		
	
}
